// ****************************************************************
// Copyright 2012, Stephan Burguchev
// e-mail: me@sburg.net
// ****************************************************************
// *
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Xml.Serialization;

namespace Updater.Common
{
    internal static class AnonymousPipeHelper
    {
        private static readonly XmlSerializer _ipdSerializer = new XmlSerializer(typeof(InterProcessData));

        public static InterProcessData ReadData(string handle)
        {
            if (handle == null)
            {
                throw new ArgumentNullException("handle");
            }

            using (PipeStream pipeClient = new AnonymousPipeClientStream(PipeDirection.In, handle))
            {
                var ipd = (InterProcessData)_ipdSerializer.Deserialize(pipeClient);
                return ipd;
            }
        }

        public static Process StartProcessAndWriteData(ProcessStartInfo startInfo, InterProcessData data)
        {
            if (startInfo == null)
            {
                throw new ArgumentNullException("startInfo");
            }

            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            try
            {
                var childProcess = new Process
                    {
                        StartInfo = startInfo
                    };

                using (var pipeServer = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
                {
                    // Pass the client process a handle to the server.
                    childProcess.StartInfo.Arguments = pipeServer.GetClientHandleAsString();

                    try
                    {
                        childProcess.Start();
                    }
                    catch (Win32Exception)
                    {
                        return null;
                    }

                    pipeServer.DisposeLocalCopyOfClientHandle();

                    _ipdSerializer.Serialize(pipeServer, data);
                }

                return childProcess;
            }
            catch (Exception ex)
            {
                throw new UpdaterException("Failed to start a child process or open an anonymous pipe to it.", ex);
            }
        }
    }
}
